﻿package net.babeuf.security 
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.GradientType;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.filters.DisplacementMapFilter;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import net.babeuf.logger.global.log;
	
	/**
	 * Create and check Captcha security fields
	 * @author damien pegoraro
	 */
	public class Captcha2 extends Sprite implements ICaptcha
	{
		[Embed(source = 'background.png')]
		private const BG : Class; 
		
		private var word:  String ; 
		
		private var output : Bitmap  ;
		private var bmp : BitmapData ; 
		
		private var bg : Bitmap ; 
		
		private var letters : Array ; 
		private var font : String ; 
						
		private static const CHARACTERS :  Array = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","0","1","2","3","4","5","6","7","8","9"] ;
		private static const COLORS : Array = [0xFF80EA, 0xFF7B7B, 0xA6C3DA, 0x59BAFF, 0x839AFF] ; 	
		
		
		/**
		 * Build a new Captcha instance. This instance can be addChilded
		 * This class only does generation and check, it doesn't include the input <code>TextField</code> and other things 
		 * @param	width the graphics width for the field
		 * @param	height the graphic height for the field
		 * @param	words a list of words that can be randomly displayed
		 * @param	fonts a list of fants that can be randomly used
		 */	
		public function Captcha2(width : Number, height : Number, letters : Array = null, font : String = "_sans", rectTemplate : DisplayObject = null  ) 
		{
			
			this.letters = letters ? letters : CHARACTERS ; 
			this.font = font ; 
					
			bg = new BG() ; 
			bg.smoothing =  true ; 
			
			log(bg.width + " , " + bg.height) ; 
			
			bmp = new BitmapData( rectTemplate ? rectTemplate.width : width, rectTemplate ? rectTemplate.height : height, true, 0) ; 
			output = new Bitmap(bmp,"auto",true) ; 
			addChild(output) ; 
			
			if ( rectTemplate ) 
			{
				x = rectTemplate.x ; 
				y = rectTemplate.y ; 
				rectTemplate.visible = false ;
				if ( rectTemplate.parent) rectTemplate.parent.addChildAt(this, rectTemplate.parent.getChildIndex(rectTemplate)) ;
			}
		}
		
				
		/**
		 * Generates a new Captcha code a draws it into the field
		 * If your words are just syllabs, you can ask for 3 words with an empty separator to produce a single 3 syllabs word
		 * @param	words the number of words to generate 
		 * @param	spacer the spacer between each word
		 */		
		public function render() : void
		{
			word = "" ; 
			for ( var i : uint = 0 ; i < 5 ; ++ i )
			{
				word += getRandomLetter().toUpperCase() ; 				
			}
			
			var aword:  Array = word.split("") ; 
						
			bmp.fillRect( bmp.rect, 0xFFFF0000);
			
			
			var small : BitmapData = bg.bitmapData.clone() ; 
			
		//	bmp.draw(bg, null, null, null, null, true);
		
			
			var cx : Number = 5 ; 			
			var j : uint = 0 ; 
			
			for each ( var l : String in aword ) 
			{
				var s:  Sprite = new Sprite() ; 
				var tf : TextField = new TextField() ; 
				tf.defaultTextFormat = new TextFormat(font, 30, pickColor() , true) ; 
				tf.height = 25 ;
				tf.autoSize = "left" ; 
				tf.text = l ; 
				tf.cacheAsBitmap = true ;  					
				s.addChild(tf) ; 			
				var tmp : BitmapData = new BitmapData(tf.width, tf.height, true, 0) ; 
				tmp.draw(tf, null, null, null, null, true ) ; 
				
				
				var m : Matrix = new Matrix() ;
				var pair : Boolean = j % 2 == 0 ;
				
				m.rotate( ( 10 * ( pair ? -1 : 1) )* Math.PI / 180 ) ; 
				m.translate(cx + ( pair ? 0 : 8), ( pair ? 5 : -1)) ; 
				
				small.draw( tmp, m, null,null,null,true ) ; 	
				cx += tmp.width ; 
				tmp.dispose() ; 
				j++ ;
				
			}
			
			var mat : Matrix = new Matrix() ; 
			mat.scale( bmp.width / small.width, bmp.height / small.height) ; 
			
			bmp.draw( small, mat, null, null, null, true) ; 
			small.dispose() ; 
		}
		
		private var last : uint ; 
		
		private function pickColor(): uint 
		{
			var current : uint = last ; 
			
			while ( current == last ) 
			{
				current = COLORS[Math.floor(Math.random() * COLORS.length)] ; 
			}
			last =  current ; 
			return current ; 
		}
		
				
		/**
		 * Check if the passed-in <code>String</code> matches the captcha value
		 * @param	value the value to check
		 * @return true if match
		 */
		public function check( value : String ) : Boolean
		{
			return value.toUpperCase() == word ;
		}
			
		
		public function getWord() : String
		{
			return word ; 
		}
				
		private function getRandomLetter(): String
		{
			return letters[Math.floor(Math.random() * letters.length)] ; 
		}
				
		private function to32Bits( color : uint ) : uint
		{
			return 0xFF000000 + color ; 
		}
	}

}